package controller

import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v4"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/github"
)

func InitLoginController(r *gin.Engine) {
	r.GET("/test-gin/auth/github", githubLoginHandler)
	r.GET("/test-gin/auth/github/callback", githubCallbackHandler)

}

var jwtSecret = []byte("your-secret-key-here")

func generateToken(userID string) string {
	claims := jwt.MapClaims{
		"user_id": userID,
		"exp":     time.Now().Add(time.Hour * 24).Unix(),
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	signedToken, _ := token.SignedString(jwtSecret)
	return signedToken
}

var githubOauthConfig = &oauth2.Config{
	ClientID:     "Ov23liSwxeXwfODxqzqI",
	ClientSecret: "3a8a429a7dfe7e8b1ed539e01394aad2e9d31776",
	RedirectURL:  "http://localhost:80/test-gin/auth/github/callback",
	Scopes:       []string{"user:email"},
	Endpoint:     github.Endpoint,
}

func githubLoginHandler(c *gin.Context) {
	state := "random-state-string"
	url := githubOauthConfig.AuthCodeURL(state)
	c.Redirect(http.StatusTemporaryRedirect, url)
}

func githubCallbackHandler(c *gin.Context) {
	code := c.Query("code")
	state := c.Query("state")
	if state != "random-state-string" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid state"})
		return
	}

	token, err := githubOauthConfig.Exchange(context.Background(), code)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "failed to exchange token" + err.Error()})
		return
	}

	client := githubOauthConfig.Client(context.Background(), token)
	resp, err := client.Get("https://api.github.com/user")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "failed to get user info"})
		return
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	var githubUser map[string]interface{}
	json.Unmarshal(body, &githubUser)

	// 生成JWT token
	jwtToken := generateToken(fmt.Sprintf("%v", githubUser["id"]))

	// 重定向回page_a.html并携带token
	redirectURL := fmt.Sprintf("/test-gin/static/page_a.html?token=%s", jwtToken)
	c.Redirect(http.StatusTemporaryRedirect, redirectURL)
}
